package org.alexsotob.roo.addon.flyway;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.junit.Test;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class PersistenceFileModifierBehaviour {

	private static final String HIBERNATE_PERSISTENCE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
			+ "<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">"
			+ "<persistence-unit name=\"persistenceUnit\" transaction-type=\"RESOURCE_LOCAL\">"
			+ "<provider>org.hibernate.ejb.HibernatePersistence</provider>"
			+ "<properties>"
			+ "<property name=\"hibernate.dialect\" value=\"org.hibernate.dialect.HSQLDialect\"/>"
			+ "<property name=\"hibernate.hbm2ddl.auto\" value=\"create\"/>"
			+ "<property name=\"hibernate.ejb.naming_strategy\" value=\"org.hibernate.cfg.ImprovedNamingStrategy\"/>"
			+ "<property name=\"hibernate.connection.charSet\" value=\"UTF-8\"/>"
			+ "</properties>" + "</persistence-unit>" + "</persistence>";

	private static final String DATANUCLEUS_PERSISTENCE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
			+ "<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">"
			+ "<persistence-unit name=\"persistenceUnit\" transaction-type=\"RESOURCE_LOCAL\">"
			+ "<provider>org.datanucleus.jpa.PersistenceProviderImpl</provider>"
			+ "<properties>"
			+ "  <property name=\"datanucleus.ConnectionDriverName\" value=\"org.hsqldb.jdbcDriver\"/>"
			+ "  <property name=\"datanucleus.autoCreateSchema\" value=\"false\"/>"
			+ "  <property name=\"datanucleus.storeManagerType\" value=\"rdbms\"/>"
			+ "  <property name=\"datanucleus.ConnectionURL\" value=\"jdbc:hsqldb:file:rootest;shutdown=true\"/>"
			+ "  <property name=\"datanucleus.ConnectionUserName\" value=\"sa\"/>"
			+ "  <property name=\"datanucleus.ConnectionPassword\" value=\"\"/>"
			+ "  <property name=\"datanucleus.autoCreateTables\" value=\"true\"/>"
			+ "  <property name=\"datanucleus.autoCreateColumns\" value=\"false\"/>"
			+ "  <property name=\"datanucleus.autoCreateConstraints\" value=\"false\"/>"
			+ "  <property name=\"datanucleus.validateTables\" value=\"false\"/>"
			+ "  <property name=\"datanucleus.validateConstraints\" value=\"false\"/>"
			+ "  <property name=\"datanucleus.jpa.addClassTransformer\" value=\"false\"/>"
			+ "</properties>" + "</persistence-unit>" + "</persistence>";

	private static final String ECLIPSELINK_PERSISTENCE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
			+ "<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">"
			+ "<persistence-unit name=\"persistenceUnit\" transaction-type=\"RESOURCE_LOCAL\">"
			+ "<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>"
			+ "<properties>"
			+ "<property name=\"eclipselink.target-database\" value=\"org.eclipse.persistence.platform.database.HSQLPlatform\"/>"
			+ "<property name=\"eclipselink.ddl-generation\" value=\"drop-and-create-tables\"/>"
			+ "<property name=\"eclipselink.ddl-generation.output-mode\" value=\"database\"/>"
			+ "<property name=\"eclipselink.weaving\" value=\"static\"/>"
			+ "</properties>" + "</persistence-unit>" + "</persistence>";

	private static final String OPENJPA_PERSISTENCE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
			+ "<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">"
			+ "<persistence-unit name=\"persistenceUnit\" transaction-type=\"RESOURCE_LOCAL\">"
			+ "<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>"
			+ "<properties>"
			+ "<property name=\"openjpa.jdbc.DBDictionary\" value=\"org.apache.openjpa.jdbc.sql.HSQLDictionary\"/>"
			+ "<property name=\"openjpa.jdbc.SynchronizeMappings\" value=\"buildSchema\"/>"
			+ "<property name=\"openjpa.RuntimeUnenhancedClasses\" value=\"supported\"/>"
			+ "</properties>" + "</persistence-unit>" + "</persistence>";

	@Test
	public void shouldModifyHibernatePersistenceConfigurations()
			throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory
				.newDocumentBuilder();
		Document hibernateDocument = documentBuilder
				.parse(new ByteArrayInputStream(HIBERNATE_PERSISTENCE
						.getBytes()));

		PersistenceFileModifier persistenceFileModifier = new HibernatePersistenceFileModifier();
		persistenceFileModifier.avoidDatabaseAutoCreation(hibernateDocument);

		Element hbm2dllProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'hibernate.hbm2ddl.auto']",
						hibernateDocument.getDocumentElement());

		assertThat(hbm2dllProperty.getAttribute("value"), is("validate"));

	}

	@Test
	public void shouldModifyDatanucleusPersistenceConfigurations()
			throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory
				.newDocumentBuilder();
		Document datanucleusDocument = documentBuilder
				.parse(new ByteArrayInputStream(DATANUCLEUS_PERSISTENCE
						.getBytes()));

		PersistenceFileModifier persistenceFileModifier = new DataNucleusPersistenceFileModifier();
		persistenceFileModifier.avoidDatabaseAutoCreation(datanucleusDocument);

		Element autocreateSchemaMappingsProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'datanucleus.autoCreateSchema']",
						datanucleusDocument.getDocumentElement());
		assertThat(autocreateSchemaMappingsProperty.getAttribute("value"),
				is("false"));

		Element autocreateTablesMappingProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'datanucleus.autoCreateTables']",
						datanucleusDocument.getDocumentElement());
		assertThat(autocreateTablesMappingProperty.getAttribute("value"),
				is("false"));

		Element autocreateColumnsMappingsProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'datanucleus.autoCreateColumns']",
						datanucleusDocument.getDocumentElement());
		assertThat(autocreateColumnsMappingsProperty.getAttribute("value"),
				is("false"));

		Element autocreateConstraintsMappingsProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'datanucleus.autoCreateConstraints']",
						datanucleusDocument.getDocumentElement());
		assertThat(autocreateConstraintsMappingsProperty.getAttribute("value"),
				is("false"));

	}

	@Test
	public void shouldModifyEclipseLinkPersistenceConfigurations()
			throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory
				.newDocumentBuilder();
		Document eclipseLinkDocument = documentBuilder
				.parse(new ByteArrayInputStream(ECLIPSELINK_PERSISTENCE
						.getBytes()));

		PersistenceFileModifier persistenceFileModifier = new EclipseLinkPersistenceFileModifier();
		persistenceFileModifier.avoidDatabaseAutoCreation(eclipseLinkDocument);

		Element ddlGenerationProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'eclipselink.ddl-generation']",
						eclipseLinkDocument.getDocumentElement());

		assertThat(ddlGenerationProperty.getAttribute("value"), is("none"));

	}

	@Test
	public void shouldModifyOpenJpaPersistenceConfigurations()
			throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory
				.newDocumentBuilder();
		Document openJpaDocument = documentBuilder
				.parse(new ByteArrayInputStream(OPENJPA_PERSISTENCE.getBytes()));

		PersistenceFileModifier persistenceFileModifier = new OpenJpaPersistenceFileModifier();
		persistenceFileModifier.avoidDatabaseAutoCreation(openJpaDocument);

		Element synchronizeMappingProperty = XmlUtils
				.findFirstElement(
						"/persistence/persistence-unit/properties/property[@name= 'openjpa.jdbc.SynchronizeMappings']",
						openJpaDocument.getDocumentElement());

		assertThat(synchronizeMappingProperty.getAttribute("value"),
				is("validate"));

	}

}
